package org.codingq92.basic.io.nio;

import java.nio.ByteBuffer;

/**
 * capacity: 缓冲区总容量（固定值，如 allocate(10) 则 capacity=10 容量一旦分配不可变）
 * position: 读写操作的 “指针”
 * 1.写模式：表示下一个写入位置，从 0 开始，写入后后移；
 * 2.读模式：表示下一个读取位置，flip 后重置为 0，读取后后移 。
 * limit: 操作的 “边界”
 * 1.写模式：limit=capacity，限制最多写入 capacity 字节；
 * 2.读模式：limit=写模式结束时的 position，限制最多读取已写入数据 。
 * mark: 标记位，用于临时保存 position，可通过 reset() 恢复（少用，上表未详细展开 ）。
 * <p>
 * 直接内存缓冲区：allocateDirect(size) 速度更快
 * 堆内存缓冲区：allocate(size)
 *
 * @author: CodingQ92
 * @date: 2025/6/26 23:04
 */
public class BufferApi {
    public static void main(String[] args) {
        // 分配一个10个字节的byte缓冲区
//        ByteBuffer byteBuffer = ByteBuffer.allocate(10); // 这是非直接内存的缓冲区
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(10); // 这是直接内存的缓冲区

        System.out.println("pos: " + byteBuffer.position() + " limit: " + byteBuffer.limit() + " cap: " + byteBuffer.capacity()); // 0 10 10
        System.out.println("-----------------------------------");
        // 写模式：往缓冲区存入数据
        String content = "abc";
        byteBuffer.put(content.getBytes());
        System.out.println("pos: " + byteBuffer.position() + " limit: " + byteBuffer.limit() + " cap: " + byteBuffer.capacity()); // 3 10 10
        System.out.println("-----------------------------------");
        // 切换读写模式：将缓冲区的界限设置为当前位置，并将当前位置设置为0 可读模式 代表 0-3位置是可以读取的了
        byteBuffer.flip();
        System.out.println("pos: " + byteBuffer.position() + " limit: " + byteBuffer.limit() + " cap: " + byteBuffer.capacity()); // 0 3 10
        System.out.println("-----------------------------------");
        // 读模式：读取缓冲区第一个字节数据
        byte b = byteBuffer.get();
        System.out.println((char) b);
        System.out.println("pos: " + byteBuffer.position() + " limit: " + byteBuffer.limit() + " cap: " + byteBuffer.capacity()); // 1 3 10
        System.out.println("-----------------------------------");
        // 清理数据
//        byteBuffer.clear(); // 读完缓冲区全部数据后，需重新写入新数据的场景（如循环读写固定长度数据 ） clear后如果不重新写入数据 还是可以读取到老数据的只是不知道有多少数据
//        byteBuffer.compact(); // 读完部分数据后，需继续写入新数据，且要保留剩余未读数据的场景
//        byte b1 = byteBuffer.get();
//        System.out.println((char) b1);
//        System.out.println("pos: " + byteBuffer.position() + " limit: " + byteBuffer.limit() + " cap: " + byteBuffer.capacity());

        byteBuffer.mark(); // 暂存当前position 上面已经读取到了 第一个字节 下面就应该是读取第二个字节了 但是 这里mark 就是记录了 position 下次通过 reset() 就可以恢复到 mark 的位置 相当于某段数据可以重复读取
        byte b1 = byteBuffer.get();
        System.out.println((char) b1);
        System.out.println("pos: " + byteBuffer.position() + " limit: " + byteBuffer.limit() + " cap: " + byteBuffer.capacity());
        System.out.println("-----------------------------------");

        byteBuffer.reset();
        byte b2 = byteBuffer.get();
        System.out.println((char) b2);
        System.out.println("pos: " + byteBuffer.position() + " limit: " + byteBuffer.limit() + " cap: " + byteBuffer.capacity());
        System.out.println("-----------------------------------");
    }
}
